﻿#include "../math_lib.h"

#include <fmt/color.h>
#include <fmt/ranges.h>
#include <fmt/std.h>
#include <gtest/gtest.h>

#include <cmath>

#include "PrePythonData.h"

#define M_PI 3.14159265358979323846
#define M_E 2.71828182845904523536

TEST(MathLibTest, Add)
{
    EXPECT_EQ(my_add(2.0, 3.0), 5.0);
    EXPECT_NEAR(my_add(1.5, 2.5), 4.0, 1e-6);
}

TEST(MathLibTest, Exp)
{
    EXPECT_NEAR(my_exp(0.0), std::exp(0.0), 1e-6);
    EXPECT_NEAR(my_exp(1.0), std::exp(1.0), 1e-6);
    EXPECT_NEAR(my_exp(2.0), std::exp(2.0), 1e-6);
}

TEST(MathLibTest, Sin)
{
    EXPECT_NEAR(my_sin(0.0), std::sin(0.0), 1e-6);
    EXPECT_NEAR(my_sin(M_PI / 2), std::sin(M_PI / 2), 1e-6);
    EXPECT_NEAR(my_sin(M_PI), std::sin(M_PI), 1e-6);
}

#define INFOLN(...)                                     \
    fmt::print(fmt::fg(fmt::color::aqua), __VA_ARGS__); \
    fmt::print("\n");

TEST(MathLibTest, CompareCppAndPythonDistances)
{
    INFOLN("");
    INFOLN("[ymy] h5file: {}", h5DumpPsx);

    // 生成 10 个随机点
    std::vector<Point> points;
    for (int i = 0; i < 10; ++i)
    {
        points.push_back({static_cast<double>(i), static_cast<double>(i * 2)});
    }

    // C++ 计算距离
    auto cpp_distances = calculate_distances(points);

    // 调用抽取的函数
    PyObject* pResult = callPythonCalculateDistances(points);
    if (!pResult)
    {
        FAIL() << "Call to 'calculate_distances_and_save' failed";
    }

    // 调用抽取的函数
    std::vector<double> py_distances = readPythonH5File(h5DumpPsx);

    //================== 比较结果
    INFOLN("C++ result:\n{:.4f}", fmt::join(cpp_distances, ", "));
    std::cout << "---------------------" << std::endl;

    INFOLN("Python result:\n{:.4f}", fmt::join(py_distances, ", "));
    INFOLN("");

    ASSERT_EQ(cpp_distances.size(), py_distances.size());
    for (size_t i = 0; i < cpp_distances.size(); ++i)
    {
        EXPECT_NEAR(cpp_distances[i], py_distances[i], 1e-6);
    }

    // 关闭 Python 解释器
    Py_Finalize();
}

int main(int argc, char** argv)
{
    testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}
